home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / DEB / DEB.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  14KB  |  674 lines

  1. /*
  2. ** Debugger with ptrace()
  3. **
  4. ** (c) Rainer Schnitker 1994
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <io.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include "ansi.h"
  14.  
  15. #ifdef __GO32__
  16. #include <sys\_process.h>
  17. #include <sys\_ptrace.h>
  18. #include <sys\_user.h>
  19. #include <sys\_reg.h>
  20. #include <sys\_signal.h>
  21. #else
  22. #include <process.h>
  23. #include <sys/ptrace.h>
  24. #include <sys/user.h>
  25. #include <sys/reg.h>
  26. #include <signal.h>
  27. #endif
  28.  
  29. #include "syms.h"
  30. #include "unassmbl.h"
  31. #include "breakp.h"
  32. #include "dpmi.h"
  33. #include "ansi.h"
  34.  
  35. extern int get_input(char *, int, int);
  36.  
  37. static int pid;
  38. static int uaddr;
  39. static char **org_env;
  40. static int sigtrap;
  41.  
  42. struct reg_names {
  43.     char *name;
  44.     int size;
  45.     int ofs;
  46. };
  47. extern struct reg_names regs[];
  48.  
  49. typedef enum {
  50.     Unknown,
  51.     CONT,
  52.     STEP,
  53.     NEXT,
  54.     LIST,
  55.     DUMP,
  56.     DISP,
  57.     SHELL,
  58.     BREAK_SET, BREAK_LIST, BREAK_CLEAR, BREAK_ENABLE, BREAK_DISABLE,
  59.     REGS,
  60.     SET,
  61.     WHERE,
  62.     FIND,
  63.     NPX,
  64.     PROCESS,
  65.     USER,
  66.     SEL,
  67.     HELP,
  68.     QUIT
  69. } deb_commands;
  70.  
  71. typedef struct {
  72.     char *cp;
  73.     deb_commands t;
  74. } item;
  75.  
  76. static item cmds[] =
  77. {
  78.     "go", CONT, "g", CONT,
  79.     "cont", CONT, "c", CONT,
  80.     "step", STEP, "s", STEP,
  81.     "next", NEXT, "n", NEXT,
  82.     "list", LIST, "l", LIST,
  83.     "dump", DUMP, "d", DUMP,
  84.     "disp", DISP,
  85.     "reg", REGS, "r", REGS,
  86.     "where", WHERE, "w", WHERE,
  87.     "find", FIND, "f", FIND,
  88.     "bp", BREAK_SET,
  89.     "bc", BREAK_CLEAR,
  90.     "bd", BREAK_DISABLE,
  91.     "be", BREAK_ENABLE,
  92.     "bl", BREAK_LIST,
  93.     "set", SET,
  94.     "process", PROCESS,
  95.     "user", USER,
  96.     "shell", SHELL,
  97.     "sel", SEL,
  98.     "npx", NPX,
  99.     "help", HELP, "h", HELP, "?", HELP,
  100.     "quit", QUIT, "q", QUIT,
  101.     0, 0
  102. };
  103.  
  104. char *sig_text[] =
  105. {
  106.     NULL,
  107.     "SIGHUP",
  108.     "SIGINT",
  109.     "SIGQUIT",
  110.     "SIGILL",
  111.     "SIGTRAP",
  112.     "SIGABRT",
  113.     "SIGEMT",
  114.     "SIGFPE",
  115.     "SIGKILL",
  116.     "SIGBUS",
  117.     "SIGSEGV",
  118.     "SIGSYS",
  119.     "SIGPIPE",
  120.     "SIGALRM",
  121.     "SIGTERM",
  122.     "16"
  123.     "17"
  124.     "SIGCLD",
  125.     "19"
  126.     "20"
  127.     "SIGBREAK"};
  128.  
  129.  
  130. static ansi_flag=0;
  131. void ansi(int fg)
  132. {
  133.     if (!ansi_flag)
  134.     return;
  135.     printf("\033[%d;%dm", (fg & A_bold) ? 1 : 0, 30+(fg&7));
  136. }
  137.  
  138. void read_memory(unsigned long addr, BYTE *buf, int len)
  139. {
  140.     unsigned long long pc, r, i;
  141.  
  142.     for (pc = addr, i = 0; pc < addr + len; pc++, i++) {
  143.     errno = 0;
  144.     r = ptrace(PTRACE_PEEKDATA, pid, pc, 0);
  145.     if (errno != 0)
  146.         break;
  147.     else
  148.         buf[i] = (BYTE) r&0xff;
  149.     }
  150. }
  151.  
  152. int ptrace_get_register(int off)
  153. {
  154.     int r;
  155.     errno = 0;
  156.     r = ptrace(PTRACE_PEEKUSER, pid, uaddr + off, 0);
  157.     if (r == -1 && errno)
  158.     perror("ptrace");
  159.     return r;
  160. }
  161.  
  162. int ptrace_put_register(int off, long value)
  163. {
  164.     int r;
  165.     errno = 0;
  166.     r = ptrace(PTRACE_POKEUSER, pid, uaddr + off, value);
  167.     if (r == -1 && errno)
  168.     perror("ptrace");
  169.     return r;
  170. }
  171.  
  172.  
  173. static void show_regs(void)
  174. {
  175.     static int seg_no[6] = { CS, DS, ES, SS, FS, GS };
  176.     static char * seg_name[6] = { "cs", "ds", "es", "ss", "fs", "gs" };
  177.  
  178.     int i, r, j = 1;
  179.  
  180.     for (i = 0; i <= 9; ++i) {
  181.     errno = 0;
  182.     r = ptrace_get_register(regs[i].ofs * 4);
  183.     if (errno != 0) {
  184.         perror("ptrace");
  185.         return;
  186.     }
  187.     if (++j == 4) {
  188.         j = 0;
  189.         putchar('\n');
  190.     }
  191.     printf("%s=%.8x ", regs[i].name + 1, r);
  192.     }
  193.     putchar('\n');
  194.     for (i = 0; i <= 5; ++i) {
  195.     errno = 0;
  196.     r = ptrace_get_register(seg_no[i] * 4);
  197.     if (errno != 0) {
  198.         perror("ptrace");
  199.         return;
  200.     }
  201.     printf("%s=%.4x ", seg_name[i], r & 0xFFFF);
  202.     }
  203.     putchar('\n');
  204. }
  205.  
  206. static int do_run(int cmd)
  207. {
  208.     int s, t, p, r;
  209.  
  210.     s = ptrace(cmd, pid, 0, 0);
  211.     if (s < 0) {
  212.     perror("ptrace");
  213.     return 0;
  214.     }
  215.     p = wait(&t);
  216.     if (p == -1)
  217.     perror("wait");
  218.     if ((t & 0377) != 0177) {
  219.     printf("Program terminated (%d)\n", (t >> 8) & 0xff);
  220.     exit(0);
  221.     }
  222.     else {
  223.     if ((t >> 8) == SIGTRAP)
  224.         sigtrap = 1;
  225.     else {
  226.         printf("process %p stopped by signal %s\n", p, sig_text[t >> 8]);
  227.         sigtrap = 0;
  228.     }
  229.     }
  230.     errno = 0;
  231.     r = ptrace_get_register(EIP * 4);
  232.     if (errno != 0) {
  233.     perror("ptrace");
  234.     return 0;
  235.     }
  236.     return r;
  237. }
  238.  
  239. static int run(int cmd)
  240. {
  241.     int i, r, t;
  242.  
  243.     if (cmd == PTRACE_STEP)
  244.     return do_run(PTRACE_STEP);
  245.  
  246.     /* RESUME, if breakpoint at eip, do one step */
  247.     r = ptrace_get_register(EIP * 4);
  248.     for (i = 0; i < MAX_BP; ++i)
  249.     if (bp[i].addr == r && bp[i].status == BP_ENABLE)
  250.         break;
  251.     if ((i < MAX_BP) &&
  252.         (ptrace(PTRACE_PEEKTEXT, pid, r, 0) & 0xFF) != 0xCD)
  253.     do_run(PTRACE_STEP);
  254.  
  255.     insert_breakpoints(pid);
  256.     r = do_run(PTRACE_RESUME);
  257.     remove_breakpoints(pid);
  258.  
  259.     /* correct eip, take back 1 step */
  260.     if (r) {
  261.     r -= sigtrap;
  262.     ptrace(PTRACE_POKEUSER, pid, uaddr + EIP * 4, r);
  263.     }
  264.     return r;
  265. }
  266.  
  267. static void dump(unsigned long n)
  268. {
  269.     static unsigned long dump_addr;
  270.     int i, j;
  271.     BYTE dump_buf[16];
  272.  
  273.     if (n)
  274.     dump_addr = n;
  275.     if (dump_addr == 0)
  276.     return;
  277.  
  278.     for (i = 0; i < 8; ++i) {
  279.     printf("%08lx: ", dump_addr);
  280.     for (j = 0; j < 16; j++) {
  281.         dump_buf[j] = (BYTE) ptrace(PTRACE_PEEKDATA, pid, dump_addr++, 0);
  282.         printf("%02X ", dump_buf[j] & 0xFF);
  283.     }
  284.     putchar(' ');
  285.     for (j = 0; j < 16; ++j) {
  286.         char c = dump_buf[j];
  287.         if (isalnum(c) || ispunct(c))
  288.         putchar(c);
  289.         else
  290.         putchar('.');
  291.     }
  292.     putchar('\n');
  293.     }
  294. }
  295.  
  296. static void command_loop(void)
  297. {
  298.     static unsigned long next_inst;
  299.     static unsigned long this_inst;
  300.     static int cmd;
  301.     static char prompt[] = "cmd:";
  302.  
  303.     unsigned long temp, list_inst;
  304.     int i, j, len;
  305.     char input[40];
  306.     char *argv[10];
  307.     char *name;
  308.  
  309.     putchar('\n');
  310.     show_regs();
  311.  
  312.     list_inst = this_inst = ptrace_get_register(EIP * 4);
  313.     next_inst = unassemble(this_inst, 1);
  314.  
  315.     while (1) {
  316.     ansi(A_white);
  317.  
  318.     printf("%s", prompt);
  319.     fflush(stdout);
  320.     len = get_input(input, 40, 0);
  321.  
  322.     ansi(A_yellow);
  323.  
  324.     /* make strings */
  325.     j = 0;
  326.     for (i = 0; input[i] != 0; i++)
  327.         if (input[i] == ' ') {
  328.         input[i] = 0;
  329.         if (input[i + 1] == ' ')
  330.             continue;
  331.         if (input[i + 1] == 0)
  332.             continue;
  333.         argv[j++] = input + i + 1;
  334.         }
  335.     argv[j] = 0;
  336.  
  337.     if (*input == 0) {    /* only return */
  338.         for (i = sizeof(prompt); i != 0; i--) {
  339.         putchar('\b'), putchar(' '), putchar('\b');
  340.         fflush(stdout);
  341.         argv[0] = NULL;
  342.         }
  343.     } else {        /* new input */
  344.         putchar('\n');
  345.         fflush(stdout);
  346.  
  347.         list_inst = this_inst;
  348.  
  349.         for (i = 0; cmds[i].cp; i++)
  350.         if (strcmp(cmds[i].cp, input) == 0) {
  351.             cmd = cmds[i].t;
  352.             i = -1;
  353.             break;
  354.         }
  355.         if (i != -1 && *input)
  356.         cmd = Unknown;
  357.     }
  358.  
  359.     switch (cmd) {
  360.  
  361.     case HELP:
  362.         printf("go <v>       g - go or continue execution\n");
  363.         printf("cont <v>     c - continue execution\n");
  364.         printf("step         s - step through instruction\n");
  365.         printf("next         n - step to next instruction\n");
  366.         printf("list <v>     l - list instructions at <v>\n");
  367.         printf("dump <v>     d - dump memory at <v>\n");
  368.         printf("disp v         - display symbol v\n");
  369.         printf("reg <m> <v>  r - show/set registers\n");
  370.         printf("where        w - display list of active functions\n");
  371.         printf("find         f - find a symbol/location (wildcard)\n");
  372.         printf("bp v           - set breakpoint at v\n");
  373.         printf("bx no          - x=List/Clear/Dis-/Enable breakpoint no\n");
  374.         printf("set m v <s>    - memory to value; size=byte/word\n");
  375.         printf("process        - show process data\n");
  376.         printf("sel s <n>      - show n selectors start with s\n");
  377.         printf("shell argv     - execute other program\n");
  378.         printf("quit         q - terminate debugger\n");
  379.         printf("help         ? - this text\n");
  380.         break;
  381.  
  382.     case CONT:
  383.         if (argv[0]) {
  384.         temp = syms_name2val(argv[0]);
  385.         if (undefined_symbol)
  386.             break;
  387.         i = set_bp(temp);
  388.         run(PTRACE_RESUME);
  389.         delete_bp(i);
  390.         } else
  391.         run(PTRACE_RESUME);
  392.         break;
  393.  
  394.     case STEP:
  395.         if ((ptrace(PTRACE_PEEKTEXT, pid, this_inst, 0) & 0xFF) == 0xCD)
  396.         goto Next;        /* not INT instr */
  397.         run(PTRACE_STEP);
  398.         break;
  399.  
  400.     case NEXT:
  401.         if (last_unassemble_unconditional || last_unassemble_jump)
  402.         run(PTRACE_STEP);
  403.         else {
  404.         Next:
  405.         i = set_bp(next_inst);
  406.         run(PTRACE_RESUME);
  407.         delete_bp(i);
  408.         }
  409.         break;
  410.  
  411.     case LIST:
  412.         if (argv[0]) {    /* weitere eingabe */
  413.         temp = syms_name2val(argv[0]);
  414.         if (!undefined_symbol)
  415.             list_inst = temp;
  416.         else
  417.             list_inst = this_inst;
  418.         }
  419.         for (i = 1; i <= 10; i++)
  420.         list_inst = unassemble(list_inst, 0);
  421.         break;
  422.  
  423.     case DUMP:
  424.         if (argv[0] == NULL) {
  425.         dump(0);
  426.         break;
  427.         }
  428.         else
  429.         temp = syms_name2val(argv[0]);
  430.         if (!undefined_symbol) {
  431.         printf("%s: adr 0x%08x val 0x%08lx\n", argv[0], temp,
  432.             ptrace(PTRACE_PEEKDATA, pid, temp, 0));
  433.         dump(temp);
  434.         }
  435.         break;
  436.  
  437.     case DISP:
  438.         if (!argv[0])
  439.         break;
  440.         temp = syms_name2val(argv[0]);
  441.         if (!undefined_symbol)
  442.         printf("%s: adr 0x%08x val 0x%08lx\n", argv[0], temp,
  443.             ptrace(PTRACE_PEEKDATA, pid, temp, 0));
  444.         break;
  445.  
  446.     case BREAK_SET:
  447.         if (argv[0]) {
  448.         temp = syms_name2val(argv[0]);
  449.         if (undefined_symbol)
  450.             break;
  451.         i = set_bp(temp);
  452.         if (i>0)
  453.             printf("breakpoint %d set\n",i);
  454.         }
  455.         break;
  456.  
  457.     case BREAK_CLEAR:
  458.         if (argv[0]) {
  459.         sscanf(argv[0], "%d", &i);
  460.         delete_bp(i);
  461.         }
  462.         break;
  463.  
  464.     case BREAK_ENABLE:
  465.         if (argv[0]) {
  466.         sscanf(argv[0], "%d", &i);
  467.         enable_bp(i);
  468.         }
  469.         break;
  470.  
  471.     case BREAK_DISABLE:
  472.         if (argv[0]) {
  473.         sscanf(argv[0], "%d", &i);
  474.         disable_bp(i);
  475.         }
  476.         break;
  477.  
  478.     case BREAK_LIST:
  479.         printf("Breakpoint list:\n");
  480.         for (i = 0; i < MAX_BP; i++)
  481.         if (bp[i].status) {
  482.             name = syms_val2name(bp[i].addr, &temp);
  483.             printf("bp %d at %08X ", i, bp[i].addr);
  484.             if (name)
  485.             printf("%s", name);
  486.             if (temp)
  487.             printf("+%lX ", temp);
  488.             if (bp[i].status == BP_DISABLE)
  489.             printf(" - disabled");
  490.             printf("\n");
  491.         }
  492.         break;
  493.  
  494.     case REGS:
  495.         if (argv[0] == NULL) {
  496.         show_regs();
  497.         break;
  498.         }
  499.         if (argv[1] == NULL)
  500.         break;
  501.         temp = syms_name2val(argv[1]);
  502.         if (undefined_symbol)
  503.         break;
  504.         j = 0;
  505.         for (i = 0; regs[i].name; i++)
  506.         if (strcmp(regs[i].name, argv[0]) == 0) {
  507.             int r = ptrace_get_register(regs[i].ofs * 4);
  508.  
  509.             j=1;
  510.             switch (regs[i].size) {
  511.             case 0:
  512.             r = (r & 0xffff00ff) | ((temp & 0xff) << 8);
  513.             break;
  514.             case 1:
  515.             * (char *) & r = * (char *) & temp;
  516.             break;
  517.             case 2:
  518.             * (short *) & r = * (short *) & temp;
  519.             break;
  520.             case 4:
  521.             r = temp;
  522.             break;
  523.             }
  524.             ptrace_put_register(regs[i].ofs * 4, r);
  525.             break;
  526.         }
  527.         if (!j)
  528.         puts("register not found");
  529.         break;
  530.  
  531.     case SHELL:
  532.         if (argv[0] == NULL)
  533.         break;
  534.         if (spawnvpe(P_WAIT, argv[0], argv, org_env) < 0)
  535.         printf("error spawn %s\n", argv[0]);
  536.         break;
  537.  
  538.     case FIND:
  539.         if (argv[0] == NULL)
  540.         break;
  541.         if (strpbrk(argv[0], "*?") != NULL) {
  542.         syms_listwild(argv[0]);
  543.         break;
  544.         }
  545.         temp = syms_name2val(argv[0]);
  546.         if (!undefined_symbol) {
  547.         name = syms_val2name(this_inst, &temp);
  548.         printf("0x%08lx %s", this_inst, name);
  549.         if (temp)
  550.             printf("+%lx", temp);
  551.         name = syms_val2line(this_inst, &i, 0);
  552.         if (name)
  553.             printf(", line %d in file %s", i, name);
  554.         putchar('\n');
  555.         }
  556.         break;
  557.  
  558.     case SET:
  559.         if (argv[0] == NULL || argv[1] == NULL)
  560.         break;
  561.         if (*(argv[0]) == '%') {
  562.         puts("Use the command 'reg' or 'r'");
  563.         break;
  564.         }
  565.         else {
  566.         DWORD pokeat;
  567.         int size;
  568.  
  569.         temp = syms_name2val(argv[1]);
  570.         if (undefined_symbol)
  571.             break;
  572.         pokeat = syms_name2val(argv[0]);
  573.         if (undefined_symbol)
  574.             break;
  575.  
  576.         if (argv[2]) {
  577.             if (*(argv[2]) == 'b')
  578.             size = 1;
  579.             else if (*(argv[2]) == 'w')
  580.             size = 2;
  581.         } else
  582.             size=0;
  583.         if (size) {   /* value */
  584.             DWORD oldv = ptrace(PTRACE_PEEKTEXT, pid, pokeat, 0);
  585.             if (size = 1)
  586.             * (char *) & temp = * (char *) & temp;
  587.             else
  588.             * (short *) & temp = * (short *) & temp;
  589.         }
  590.         ptrace(PTRACE_POKETEXT, pid, pokeat, temp);
  591.         }
  592.         break;
  593.  
  594.     case PROCESS:
  595.         printf("pid %d ppid %d\n\n", getpid(), getppid());
  596.         PrintFreeMemInfo();
  597.         break;
  598.  
  599.     case SEL:
  600.         if (argv[0] == NULL)
  601.         break;
  602.         if (argv[1] == NULL)
  603.         i = 1;
  604.         else
  605.         i = atoi(argv[1]);
  606.         temp = syms_name2val(argv[0]);
  607.         if (undefined_symbol)
  608.         break;
  609.         show_descriptor(temp, i);
  610.         break;
  611.  
  612.     case QUIT:
  613.         ansi(A_white);
  614.         return;
  615.  
  616.     case Unknown:
  617.         printf("unknown command, try (H)elp or ?\n");
  618.         break;
  619.  
  620.     }   /* switch */
  621.  
  622.     if (cmd == CONT || cmd == NEXT || cmd == STEP) {
  623.         list_inst = this_inst = ptrace_get_register(EIP * 4);
  624.         next_inst = unassemble(this_inst, 1);
  625.     }
  626.     }    /* while */
  627. }
  628.  
  629. int main(int argc, char **argv, char **envp)
  630. {
  631.     static char debug_file[260];
  632.     struct user u;
  633.     char *term;
  634.  
  635.     term = getenv("TERM");
  636.     if (term != NULL && strncmp(term, "ansi", 4) == 0) {
  637.     ansi_flag = 1;
  638.     }
  639.  
  640.     org_env = envp;
  641.     if (argv[1])
  642.     strcpy(debug_file, argv[1]);
  643.  
  644.     for (;;) {
  645.     if (access(debug_file, 0) < 0)
  646.         strcat(debug_file, ".exe");
  647.  
  648.     pid = spawnvpe(P_DEBUG | P_WINDOWED, debug_file, argv + 1, envp);
  649.  
  650.     if (pid < 0) {
  651.         perror("Debugger spawnve");
  652.         printf("New Filename:");
  653.         gets(debug_file);
  654.     }
  655.     else
  656.         break;
  657.     }
  658.  
  659.     printf("child PID %d\n", pid);
  660.     errno = 0;
  661.     uaddr = ptrace(PTRACE_PEEKUSER, pid, (char *) &u.u_ar0 - (char *) &u, 0);
  662.     if (errno != 0)
  663.     perror("ptrace");
  664.     uaddr -= 0xe0000000;
  665.  
  666.     printf("debugging file %s\n", debug_file);
  667.     fflush(stdout);
  668.  
  669.     syms_init(debug_file);
  670.     command_loop();
  671.  
  672.     return (0);
  673. }
  674.